package com.jfast.framework.server.jetty;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.jfast.framework.kit.PathKit;

public abstract class JfastClassLoaderScanner {

	private final Map<String,TimeSize> preScan = new HashMap<String,TimeSize> ();
	private final Map<String,TimeSize> curScan = new HashMap<String,TimeSize> ();
	
	private ScheduledExecutorService scheduledExecutorService;
	
	abstract void onChange();
	
	public void start() {
		Task task = new Task();
		getScheduledExecutorService().scheduleAtFixedRate(task, 0, 5L,TimeUnit.SECONDS);
	}
	
	public ScheduledExecutorService getScheduledExecutorService() {
		if (scheduledExecutorService == null) {
			scheduledExecutorService = Executors.newScheduledThreadPool(1);
		}
		return scheduledExecutorService;
	}
	
	private void working() {
		scan(new File(PathKit.getRootClassPath()));
		compare();
		
		preScan.clear();
		preScan.putAll(curScan);
		curScan.clear();
	}
	
	private void compare() {
		if (preScan.size() == 0)
			return;
		
		if (!preScan.equals(curScan))
			onChange();
	}

	private void scan(File file) {
		if (file == null || !file.exists())
			return ;
		
		if (file.isFile()) {
			try {
				curScan.put(file.getCanonicalPath(), new TimeSize(file.lastModified(),file.length()));
			} catch (IOException e) {
				
			}
		}
		else if (file.isDirectory()) {
			File[] fs = file.listFiles();
			if (fs != null)
				for (File f : fs)
					scan(f);
		}
	}
	
	class Task implements Runnable{

		@Override
		public void run() {
			working();
		}
	}
}

class TimeSize {
	
	final long time;
	final long size;
	
	public TimeSize(long time, long size) {
		this.time = time;
		this.size = size;
	}
	
	public int hashCode() {
		return (int)(time ^ size);
	}
	
	public boolean equals(Object o) {
		if (o instanceof TimeSize) {
			TimeSize ts = (TimeSize)o;
			return ts.time == this.time && ts.size == this.size;
		}
		return false;
	}
	
	public String toString() {
		return "[t=" + time + ", s=" + size + "]";
	}
}
